Skip to content

Replace libc printf with eyalroz/printf and add streaming status formatting.#23694

Merged
benvanik merged 1 commit intomainfrom
users/benvanik/printf
Mar 9, 2026
Merged

Replace libc printf with eyalroz/printf and add streaming status formatting.#23694
benvanik merged 1 commit intomainfrom
users/benvanik/printf

Conversation

@benvanik
Copy link
Collaborator

@benvanik benvanik commented Mar 9, 2026

Integrates eyalroz/printf as a vendored dependency to replace all libc snprintf/vsnprintf calls across the runtime. This gives us a consistent, portable printf implementation across all platforms (including embedded and bare-metal targets) with no platform-specific quirks.

Beyond the drop-in replacement, this extends the status formatting API with streaming support:

  • Add iree_status_format_to: callback-based streaming formatter that avoids contiguous buffers and pre-measurement passes. The callback returns bool for flow control, enabling early termination on buffer full or allocation failure.

  • Add iree_string_builder_append_status: single-pass status-to-builder formatting via iree_status_format_to, resolving the status/string_builder dependency cycle that previously required a local copy in libhsa.c.

  • Rewrite iree_status_fprint to stream directly to FILE* with zero heap allocation (previously required a contiguous buffer).

  • Rewrite iree_status_to_string as single-pass using string builder instead of two-pass measure-then-format.

  • Fix va_copy usage in status allocation: use C99 va_copy for the two-pass measure-then-format pattern instead of calling va_start twice on the same parameter (implementation-defined behavior).

  • Convert Status::ToString (C++) and ApiStatusToString (Python bindings) from two-pass iree_status_format to single-pass iree_status_format_to.

  • Replace HIP dynamic_symbols.c allocate-format-free pattern with direct iree_string_builder_append_status (eliminates intermediate heap allocation).

  • RISC-V toolchain fix: strip debug info from libgcc.a during CMake configure. eyalroz/printf's long double support in %Lf/%Le compiles va_arg(args, long double) which on RISC-V (128-bit quad precision) generates references to __extenddftf2/__trunctfdf2 soft-float builtins. These are resolved from libgcc.a, but the GCC 12.2.0-compiled objects in that archive contain DWARF debug info with relocation types 60/61 (in .debug_rnglists and .debug_loclists sections) that LLD cannot parse. The pre-built RISC-V toolchain lacks compiler-rt builtins as an alternative, so we strip the debug metadata from libgcc.a at configure time using llvm-objcopy --strip-debug. This preserves all code and data sections and is idempotent. The strip runs inside the RISCV_TOOLCHAIN_ROOT guard so users with their own toolchains are unaffected. Verified locally with the same toolchain used in CI (toolchain_iree_manylinux_2_28_20231012).

ci-extra: all

@benvanik benvanik requested a review from stellaraccident March 9, 2026 00:32
@benvanik benvanik added runtime Relating to the IREE runtime library post-merge-review Ben's special place. People can pick these up and review them for forward fixes if interested. labels Mar 9, 2026
@benvanik benvanik force-pushed the users/benvanik/printf branch 3 times, most recently from 3c585a3 to 32777ac Compare March 9, 2026 01:27
…atting.

Integrates eyalroz/printf as a vendored dependency to replace all libc
snprintf/vsnprintf calls across the runtime. This gives us a consistent,
portable printf implementation across all platforms (including embedded
and bare-metal targets) with no platform-specific quirks.

Beyond the drop-in replacement, this extends the status formatting API
with streaming support:

- Add iree_status_format_to: callback-based streaming formatter that
  avoids contiguous buffers and pre-measurement passes. The callback
  returns bool for flow control, enabling early termination on buffer
  full or allocation failure.

- Add iree_string_builder_append_status: single-pass status-to-builder
  formatting via iree_status_format_to, resolving the status/string_builder
  dependency cycle that previously required a local copy in libhsa.c.

- Rewrite iree_status_fprint to stream directly to FILE* with zero
  heap allocation (previously required a contiguous buffer).

- Rewrite iree_status_to_string as single-pass using string builder
  instead of two-pass measure-then-format.

- Fix va_copy usage in status allocation: use C99 va_copy for the
  two-pass measure-then-format pattern instead of calling va_start
  twice on the same parameter (implementation-defined behavior).

- Convert Status::ToString (C++) and ApiStatusToString (Python bindings)
  from two-pass iree_status_format to single-pass iree_status_format_to.

- Replace HIP dynamic_symbols.c allocate-format-free pattern with
  direct iree_string_builder_append_status (eliminates intermediate
  heap allocation).

RISC-V toolchain fix: strip debug info from libgcc.a during CMake
configure. eyalroz/printf's long double support in %Lf/%Le compiles
va_arg(args, long double) which on RISC-V (128-bit quad precision)
generates references to __extenddftf2/__trunctfdf2 soft-float builtins.
These are resolved from libgcc.a, but the GCC 12.2.0-compiled objects
in that archive contain DWARF debug info with relocation types 60/61
(in .debug_rnglists and .debug_loclists sections) that LLD cannot
parse. The pre-built RISC-V toolchain lacks compiler-rt builtins as
an alternative, so we strip the debug metadata from libgcc.a at
configure time using llvm-objcopy --strip-debug. This preserves all
code and data sections and is idempotent. The strip runs inside the
RISCV_TOOLCHAIN_ROOT guard so users with their own toolchains are
unaffected. Verified locally with the same toolchain used in CI
(toolchain_iree_manylinux_2_28_20231012).

Co-Authored-By: Claude <[email protected]>
@benvanik benvanik force-pushed the users/benvanik/printf branch from 32777ac to abb5207 Compare March 9, 2026 02:18
@benvanik benvanik marked this pull request as ready for review March 9, 2026 04:15
@benvanik
Copy link
Collaborator Author

benvanik commented Mar 9, 2026

mac failures are disk space, linux arm64 is unrelated and have a pending a fix.

@benvanik benvanik merged commit b4af1cd into main Mar 9, 2026
64 of 66 checks passed
@benvanik benvanik deleted the users/benvanik/printf branch March 9, 2026 05:28
AaronStGeorge pushed a commit to ROCm/TheRock that referenced this pull request Mar 16, 2026
## Summary
- iree-org/iree#23694 (merged 2026-03-09) replaced all libc
`snprintf`/`vsnprintf` calls in the IREE runtime with `eyalroz/printf`,
making `third_party/printf` an unconditional build dependency
(`printf::printf` is required by `iree::base`).
- `third_party/printf` was missing from the default
`--nested-submodules` list for `iree` in `fetch_sources.py`, causing it
not to be fetched and the IREE build to fail.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: zjgarvey <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

post-merge-review Ben's special place. People can pick these up and review them for forward fixes if interested. runtime Relating to the IREE runtime library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant